/*
 * Copyright (c) 2021 Zsj. All rights reserved.
 */

package com.jzz.crawlerweb.handler.data;

import org.reflections.Reflections;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ConfigurationBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

public class Captcha<T> {
    private static final Logger logger = LoggerFactory.getLogger(Captcha.class);
    private static Map<String, Class<? extends Captcha>> components;

    // 加锁，防止线程冲突
    private static final Object LOCK = new Object();

    private String raw;

    public Captcha() {

    }

    public Captcha(String raw) {
        this.raw = raw;
    }

    public static Captcha getInstance(String type, String raw) {
        if (components == null) {
            synchronized (LOCK) {
                // 二次校验，防止多次操作
                if (components == null) {
                    components = new ConcurrentHashMap<>();

                    // 进行初始化操作，扫描所有的处理器类
                    Reflections reflections = new Reflections(
                            new ConfigurationBuilder().forPackages("com.jzz.crawlerweb.handler")
                                    .addScanners(new SubTypesScanner())
                    );
                    Set<Class<? extends Captcha>> set = reflections.getSubTypesOf(Captcha.class);

                    // 遍历所有子类，将其放进Map中
                    for (Class<? extends Captcha> cls : set) {
                        String typeName;
                        String clsName = cls.getSimpleName();

                        if (clsName.endsWith("Captcha")) {
                            typeName = clsName.substring(0, clsName.lastIndexOf("Captcha")).toLowerCase();
                            if (!typeName.isEmpty()) {
                                components.put(typeName, cls);
                            }
                        }
                    }
                }
            }
        }

        Class<? extends Captcha> clazz = components.get(type.toLowerCase());
        if (clazz != null) {
            try {
                Captcha instance = clazz.getDeclaredConstructor().newInstance();
                instance.setRaw(raw);
                return instance;
            } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                logger.error("Error while creating captcha: ", e);
            }
        }
        return new Captcha(raw);
    }

    public String getRaw() {
        return raw;
    }

    public void setRaw(String raw) {
        this.raw = raw;
    }

    public T getRendered() {
        return null;
    }

    @Override
    public String toString() {
        return "Captcha{" +
                "raw='" + raw + '\'' +
                '}';
    }
}
